﻿using System;
using System.Security.Cryptography;
using System.Text;

namespace OpenClientDemo
{
    public static class SsoHelper
    {
        /// <summary>
        ///     date time ticks at 1970-01-01
        /// </summary>
        private const long TicksAt1970 = 621355968000000000L;

        /// <summary>
        ///    url format of sso
        /// </summary>
        private const string SsoUrlFormat = "http://{0}/login/sso.init.do?userName={1}&timestamp={2}&corpCode={3}&sign={4}";

        /// <summary>
        ///     returns ticks of specified date time after date 1970-01-01 . 
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        private static long GetTicksWithJavaTime(DateTime dateTime)
        {
            return (dateTime.ToUniversalTime().Ticks - TicksAt1970) / 10000;
        }

        /**/
        /// <summary>
        /// MD5　32位加密
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string Md5To32(this string content)
        {
            string result = string.Empty;
            var md5 = MD5.Create();//实例化一个md5对像
            // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
            byte[] md5Bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(content));
            // 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得
            for (int i = 0; i < md5Bytes.Length; i++)
            {
                // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母，如果使用大写（X）则格式后的字符是大写字符
                result += md5Bytes[i].ToString("x").PadLeft(2, '0');

            }
            return result;
        }

        /// <summary>
        ///     生成sso签名
        /// </summary>
        /// <param name="action">动作标识</param>
        /// <param name="secret">sso密钥</param>
        /// <param name="corpCode">公司编号</param>
        /// <param name="loginName">登录用户名</param>
        /// <param name="timestamp">时间戳</param>
        /// <returns>生成的签名</returns>
        public static string CalculateSign(string action, string secret, string corpCode, string loginName,
             long timestamp)
        {
            string signingText = secret + "|" + action + "|" + corpCode + "|" + loginName + "|" + timestamp + "|" + secret;
            return signingText.Md5To32();
        }

        /// <summary>
        ///     根据指定参数生成单点登录的url
        /// </summary>
        /// <param name="hostUrl"></param>
        /// <param name="secret">sso密钥</param>
        /// <param name="corpCode">公司编号</param>
        /// <param name="loginName">登录用户名</param>
        /// <param name="returnUrl">登录后跳转的url 默认为null, 即不跳转</param>
        /// <returns>生成后的单点登录的url</returns>
        public static string GenerateSsoUrl(string hostUrl, string secret, string corpCode, string loginName, string returnUrl = null)
        {
            var ticksWithJavaTime = GetTicksWithJavaTime(DateTime.Now);
            var calculateSign = CalculateSign("sso", secret, corpCode, loginName, ticksWithJavaTime);
            var ssoUrl = string.Format(SsoUrlFormat, hostUrl, loginName, ticksWithJavaTime, corpCode, calculateSign);
            if (!string.IsNullOrWhiteSpace(returnUrl))
            {
                ssoUrl += "&returnUrl=" + returnUrl;
            }
            return ssoUrl;
        }
    }
}
